package servlets;

import net.sf.json.JSONObject;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;

/**
 * 产生验证码的servlet
 */
@WebServlet(name = "ValidationcodeServlet", urlPatterns = "/valicode")
public class ValidationcodeServlet extends HttpServlet {
    /**
     * 旋转并且画出指定字符串
     *
     * @param s          需要旋转的字符串
     * @param x          字符串的x坐标
     * @param y          字符串的Y坐标
     * @param g          画笔g
     * @param degreeSize 旋转的角度
     */
    private void RotateString(String s, int x, int y, Graphics g, int degreeSize) {
        Random random = new Random();
        Graphics2D g2d = (Graphics2D) g.create();
        //   平移原点到图形环境的中心  ,这个方法的作用实际上就是将字符串移动到某一个位置
        g2d.translate(x - 1, y + 3);
        //   旋转文本
        g2d.rotate(random.nextInt(degreeSize) * Math.PI / 180);
        //特别需要注意的是,这里的画笔已经具有了上次指定的一个位置,所以这里指定的其实是一个相对位置
        g2d.drawString(s, 0, 0);
    }

    /**
     * 随机产生干扰线条
     *
     * @param width
     * @param height
     * @param minMany 最少产生的数量
     * @param g
     */
    private void CreateRandomLine(int width, int height, int minMany, Graphics g) {
        Random rand = new Random();
        for (int i = 0; i < rand.nextInt(minMany) + 5; i++) {
            int x1 = rand.nextInt(width) % 15;
            int y1 = rand.nextInt(height);
            int x2 = (int) (rand.nextInt(width) % 40 + width * 0.9);
            int y2 = rand.nextInt(height);
            g.setColor(g.getColor());
            g.drawLine(x1, y1, x2, y2);
        }
    }

    //

    /**
     * 产生随即的字体
     *
     * @param fontsize
     * @return 字体
     */
    private Font getFont(int fontsize) {
        Random random = new Random();
        Font font[] = new Font[5];
        font[0] = new Font("Ravie", Font.PLAIN, fontsize);
        font[1] = new Font("Antique Olive Compact", Font.PLAIN, fontsize);
        font[2] = new Font("Forte", Font.PLAIN, fontsize);
        font[3] = new Font("Wide Latin", Font.PLAIN, fontsize);
        font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, fontsize);
        return font[random.nextInt(5)];
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        int width = 200, height = 50, num = 5;
        int base = width / num;

        // 设置响应头 Content-type类型
        response.setContentType("image/jpeg");
        // 以下三句是用于设置页面不缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "No-cache");
        response.setDateHeader("Expires", 0);

        OutputStream os = response.getOutputStream();

        // 建立指定宽、高和BufferedImage对象
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);

        Graphics g = image.getGraphics(); // 该画笔画在image上
        Color c = g.getColor(); // 保存当前画笔的颜色，用完画笔后要回复现场
        g.setColor(new Color(125, 125, 125));
        g.fillRect(0, 0, width, height);

        char[] ch = "abcdefghjkmnpqrstuvwxyz23456789".toCharArray(); // 随即产生的字符串
        //以下难辨认
        // 不包括 i
        // l(小写L)
        // o（小写O）
        // 1（数字1）0(数字0)
        int length = ch.length; // 随即字符串的长度
        String sRand = ""; // 保存随即产生的字符串
        Random random = new Random();
        for (int i = 0; i < num; i++) {
            // 设置字体
            g.setFont(getFont(base));
            // 随即生成0-9的数字
            String rand = Character.toString(ch[random.nextInt(length)]);
            sRand += rand;
            // 设置随机颜色
            g.setColor(new Color(random.nextInt(255), random.nextInt(255),
                    random.nextInt(255)));
            RotateString(rand, base * i + 6, height / 2, g, 50);//添加旋转效果
            //g.drawString(rand, base * i + 6, base);
        }
        // 产生随即干扰点
        for (int i = 0; i < 20; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            g.drawOval(x1, y1, 2, 2);
        }
        //产生随机干扰线
        CreateRandomLine(width, height, 5, g);

        g.setColor(c); // 将画笔的颜色再设置回去
        g.dispose();

        // 将验证码记录到session
        request.getSession().setAttribute("safecode", sRand);
        // 输出图像到页面
        ImageIO.write(image, "JPEG", os);
        //
        System.out.println("验证码为" + sRand);
    }

    /**
     * 验证验证码是否正确
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter pw = response.getWriter();
        JSONObject result = new JSONObject();

        String code = (String) request.getSession().getAttribute("safecode");
        String tocheck = request.getParameter("code");
        if (tocheck.equals(code)) {
            result.put("canReg", true);
        } else {
            result.put("canReg", false);
        }
        pw.write(result.toString());
    }
}
